#pragma once
#include "yolo_detect_pkg/engine.hpp"
#include <fstream>
#include <random>
#include <sstream>
#include <iomanip>
std::string floatToStringWithTwoDecimals(float value);
// Utility method for checking if a file exists on disk
inline bool doesFileExist(const std::string &name) {
    std::ifstream f(name.c_str());
    return f.good();
}

struct Object {
    // The object class.
    int label{};
    // The detection's confidence probability.
    float probability{};
    // The object bounding box rectangle.
    cv::Rect_<float> rect;
    // Semantic segmentation mask
    cv::Mat boxMask;
    // Pose estimation key points
    std::vector<float> kps{};
    
    
};

struct Detection{
    // 当前物体的执行度
    float confidence;
    // 目标框的位置
    cv::Rect_<float> bbox;
    // 目标的类别ID
    int class_id;
    // 对应类的名称
    std::string class_name;
};


// 配置YOLOV10检测器的行为。
// 可以通过命令行参数传递这些参数。
struct YOLOV10Config {
    // 用于推理的精度
    Precision precision = Precision::FP32;
    // 校准数据目录。使用INT8精度时必须指定。
    std::string calibrationDataDirectory{};
    // 每个先验框的置信度分割值
    float confidence_threshold = 0.5;
    int topK = 100;
    std::string Onnx_path = {};
    // 类别阈值（默认是COCO类）
    std::vector<std::string> classNames{};
    float nms_threshold = 0.4;
};


class YOLOV10 {
public:
    // Builds the onnx model into a TensorRT engine, and loads the engine into memory
    YOLOV10();


    // 进行对应的后处理工作
    std::vector<Detection> filterDetections(const std::vector<float> &results);

    // Draw the object bounding boxes and labels on the image
    void drawObjectLabels(cv::Mat &image, const std::vector<Object> &objects, unsigned int scale = 2);


    std::vector<Detection>  YoloDetectObjects(cv::Mat &inputImageBGR);
    std::vector<Detection>  YoloDetectObjects(cv::cuda::GpuMat &inputImageBGR);
    cv::Mat YOLOv10_Draw_Line(const cv::Mat&, const std::vector<Detection>&);
    // 创建模型并进行保存使用
    bool CreateModle(std::string OnnxModepath);
    void YOLOv10InitByConfigure( const YOLOV10Config & configure);
    void YOLOV10Inite();

private:
    


    std::unique_ptr<Engine<float>> m_trtEngine = nullptr;
    
   
    std::vector<std::vector<cv::cuda::GpuMat> >YOLOV10_preprocess(cv::cuda::GpuMat&);
    cv::cuda::GpuMat resize_image(cv::cuda::GpuMat & srcimg);
    
    cv::Scalar getRandomColor();


   
  
    // Used for image preprocessing
    // YOLOV10 model expects values between [0.f, 1.f] so we use the following params
    const std::array<float, 3> SUB_VALS{0.f, 0.f, 0.f};
    const std::array<float, 3> DIV_VALS{1.f, 1.f, 1.f};
    const bool NORMALIZE = true;

    float m_ratio = 1;
    float m_imgWidth = 0;
    float m_imgHeight = 0;

    
   int TOP_K;

    

    // YOLOV10 属性
    //先验框的属性
    int newh = {};
    int neww = {};
    int paddtop = {};
    int paddleft = {};
    int in_p_width;
    int in_p_height;
    int input_image_height = {};
    int input_image_widht = {};

    // keep_ratio：不发生畸变
    bool keep_ratio = true;
    



    Precision precision = Precision::FP32;
    // 校准数据目录。使用INT8精度时必须指定。
    std::string calibrationDataDirectory{};
    // 每个先验框的置信度分割值
    float CONFIDENCE_THRESHOLD = 0.5;
    float NMS_THRESHOLD = 0.4;
    int topK = 100;
    std::string MODE_PATH = {};
    // 类别阈值（默认是COCO类）
    std::vector<std::string> CLASSNAMES{};
};